package com.feilong.modules.service.goods.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.feilong.modules.client.auth.AuthClient;
import com.feilong.modules.common.enums.DeleteEnum;
import com.feilong.modules.common.exception.APIException;
import com.feilong.modules.common.request.WxOperateDbRequest;
import com.feilong.modules.dao.goods.GoodsCategoryDao;
import com.feilong.modules.model.goods.constant.GoodsCategoryConstant;
import com.feilong.modules.model.goods.constant.GoodsInfoConstant;
import com.feilong.modules.model.goods.po.CategoryDetailPO;
import com.feilong.modules.model.goods.po.GoodsCategoryPO;
import com.feilong.modules.model.goods.request.AddCategoryRequest;
import com.feilong.modules.model.goods.request.UpdateCategoryRequest;
import com.feilong.modules.model.goods.vo.GoodsCategoryVO;
import com.feilong.modules.service.goods.CategoryDetailService;
import com.feilong.modules.service.goods.GoodsCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class GoodsCategoryServiceImpl extends ServiceImpl<GoodsCategoryDao, GoodsCategoryPO> implements GoodsCategoryService {

    @Value("${feilongshop.config.appid}")
    private String APPID;

    @Value("${feilongshop.config.app-secret}")
    private String APPSECRET;

    @Value("${feilongshop.config.env}")
    private String ENV;

    @Resource
    private AuthClient authClient;

    @Resource
    private CategoryDetailService categoryDetailService;

    /**
     * 获取所有商品分类
     * @return
     */
    @Override
    public List<GoodsCategoryPO> getCategory() {
        return this.list(new LambdaQueryWrapper<GoodsCategoryPO>()
                .select(GoodsCategoryPO :: getId, GoodsCategoryPO::getCategory)
                .eq(GoodsCategoryPO::getIsDelete, DeleteEnum.NO.getCode())
                .orderByAsc(GoodsCategoryPO :: getId)
        );
    }

    /**
     * 根据商品分类id获取所有商品
     * @param categoryId
     * @return
     */
    public List<GoodsCategoryVO> getCategoryDetail(Integer categoryId){
        List<GoodsCategoryVO> list = this.baseMapper.getCategoryDetail(categoryId);
        return list;
    }

    /**
     * 更新商品分类
     * @param request
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCategory(UpdateCategoryRequest request) {
        // 更新mysql数据
        // 更新分类表
        this.updateById(new GoodsCategoryPO().builder()
                .id(request.getCategoryId())
                .category(request.getCategoryName())
                .build()
        );
        // 更新详情表 先删除旧数据，再插入新数据
        categoryDetailService.remove(new LambdaQueryWrapper<CategoryDetailPO>().eq(CategoryDetailPO::getCategoryId, request.getCategoryId()));
        List<CategoryDetailPO> categoryList = new ArrayList<>();
        request.getCategoryList().forEach(item ->{
            CategoryDetailPO category = new CategoryDetailPO();
            BeanUtils.copyProperties(item, category);
            categoryList.add(category);
        });
        categoryDetailService.saveBatch(categoryList);
        // TODO: 2021/4/18 以后需要移除云开发数据库的更新
        // 更新云开发数据库
        updateCloudCategory(request);
    }

    /**
     * 添加商品分类
     * @param request
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCategory(AddCategoryRequest request) {
        if (request.getCategoryList().size() == 0) {
            throw new APIException(GoodsCategoryConstant.ADD_CATEGORY_FAIL);
        }
        // mysql添加数据
        // 分类表
        GoodsCategoryPO goodsCategoryPO = new GoodsCategoryPO();
        goodsCategoryPO.setCategory(request.getCategoryName());
        goodsCategoryPO.setCreateTime(LocalDateTime.now());
        this.save(goodsCategoryPO);
        // 获取分类表自增id
        Integer categoryId = goodsCategoryPO.getId();
        // 分类详情表
        List<GoodsCategoryVO> categoryList = request.getCategoryList();
        List<CategoryDetailPO> categoryDetailPOS = new ArrayList<>();
        categoryList.forEach(item->{
            item.setCategoryId(categoryId);
            CategoryDetailPO categoryDetail = new CategoryDetailPO();
            BeanUtils.copyProperties(item, categoryDetail);
            categoryDetailPOS.add(categoryDetail);
        });
        categoryDetailService.saveBatch(categoryDetailPOS);
        // TODO: 2021/4/19 以后需要移除云开发数据库的添加
        // 云开发数据库插入数据
        addCloudCategory(categoryList, categoryId, request.getCategoryName());
    }

    /**
     * 根据分类id删除商品分类信息
     * @param categoryId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delCategory(Integer categoryId) {
        // mysql删除分类
        // 分类表
        this.updateById(new GoodsCategoryPO().builder()
                .id(categoryId)
                .isDelete(DeleteEnum.YES.getCode())
                .build()
        );
        // 分类详情表
        categoryDetailService.remove(new LambdaQueryWrapper<CategoryDetailPO>().eq(CategoryDetailPO::getCategoryId, categoryId));
        // TODO: 2021/4/19 以后需要移除云开发数据库的删除
        // 云开发数据库删除数据
        delCloudCategory(categoryId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void delCloudCategory(Integer categoryId) {
        // 获取AccessToken
        String token = getAccessToken();
        WxOperateDbRequest request = new WxOperateDbRequest();
        request.setEnv(ENV);
        request.setQuery("db.collection(\"category\").where({menu:{menu_id:" + categoryId + "}}).remove()");
        String result = authClient.deleteCloudDbInfo(request, token);
        log.info("云开发数据库删除商品分类 id:{}, 结果：{}", categoryId, result);
    }

    @Transactional(rollbackFor = Exception.class)
    public void addCloudCategory(List<GoodsCategoryVO> categoryList, Integer categoryId, String categoryName) {
        // 获取AccessToken
        String token = getAccessToken();
        WxOperateDbRequest request = new WxOperateDbRequest();
        request.setEnv(ENV);
        request.setQuery("db.collection(\"category\").add({data:{" +
                "menu:{menu_id:" + categoryId + ",menu_name:\"" + categoryName + "\"}," +
                "goods:" + JSONArray.toJSONString(categoryList) + "}})"
        );
        String result = authClient.insertCloudDbInfo(request, token);
        log.info("云开发数据库插入商品分类{}, 结果：{}", categoryName, result);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateCloudCategory(UpdateCategoryRequest categoryDetail) {
        // 获取AccessToken
        String token = getAccessToken();
        WxOperateDbRequest request = new WxOperateDbRequest();
        request.setEnv(ENV);
        request.setQuery("db.collection(\"category\").where({menu:{menu_id:" + categoryDetail.getCategoryId() + "}}).update({data:{" +
                "menu:{menu_id:" + categoryDetail.getCategoryId() + ",menu_name:\"" + categoryDetail.getCategoryName() + "\"}," +
                "goods:" + JSONArray.toJSONString(categoryDetail.getCategoryList()) + "}})"
        );
        String result = authClient.updateCloudDbInfo(request, token);
        log.info("云开发数据库更新商品分类结果：{}", result);
    }

    /**
     * 根据商品id获取商品所属分类
     * @param goodsId
     * @return
     */
    public List<Integer> getGoodsCategoryId(Integer goodsId){
        if (goodsId == null) {
            throw new APIException(GoodsInfoConstant.GOODS_INFO_ERROR);
        }
        return this.baseMapper.getGoodsCategoryId(goodsId);
    }

    /**
     * 获取小程序AccessToken
     * @return
     */
    public String getAccessToken(){
        String result = authClient.getAccessToken(APPID,APPSECRET);
        JSONObject data = JSONObject.parseObject(result);
        String token = data.getString("access_token");
        log.info("获取到的微信云开发AccessToken为 -> {}", token);
        return token;
    }
}
